#ifndef _X_SQLBUILDER_H
#define _X_SQLBUILDER_H
#include <string.h>
#include <mysql/mysql.h>
#include <iostream>
#include "Data_def.h"
namespace x_3rd
{
    class x_sql_builder{
        public:
            static std::string escapeString(MYSQL* mysql_ref,const std::string& sFrom)
            {
                if(mysql_ref == NULL)
                {
                    return "";
                }
                std::string sTo;
                std::string::size_type iLen = sFrom.length() * 2 + 1;
                char *pTo = (char *)malloc(iLen);

                memset(pTo, 0x00, iLen);
                mysql_real_escape_string(mysql_ref, pTo, sFrom.c_str(), sFrom.length());
                sTo = pTo;
                free(pTo);
                return sTo;
            }
    };

    class x_insert_sql_builder{
        public:
            static std::string build(MYSQL* mysql_ref,const std::string& table_name,const DataRecord& record)
            {
                if(!mysql_ref) return "";
                //insert into tbname(name,sex,age) values('heyongtao','n',10)
                std::string str = "insert into " + table_name;
                std::string field_names = "(";
                std::string values = " values(";
                for(auto& iter : record)
                {
                    field_names += iter.first + ",";
                    DATATYPE type = iter.second.first;
                    if(type == DATATYPE::DATA_INT)
                    {
                        values += iter.second.second + ",";
                    }
                    else if(type == DATATYPE::DATA_STRING)
                    {
                        values += "\"" + x_sql_builder::escapeString(mysql_ref,iter.second.second) + "\"" + ",";
                    }
                }
                field_names.pop_back();
                field_names += ')';
                values.pop_back();
                values += ')';
                std::string sql = str + field_names + values;
                return sql;
            }
    };
    class x_query_sql_builder{
        public:
            static std::string build(MYSQL* mysql_ref,const std::string& table_name,const std::vector<std::string>& fields,\
            const DataRecord& record , Conditions condis)
            {
                if(!mysql_ref) return "";
                //select name,sex,age from table_name where age=10
                std::string str = "select ";
                std::string field_names = "" ,wheres = " where ";
                for(auto& fs : fields)
                {
                    field_names += fs + ",";
                }
                field_names.pop_back();
                bool is_has_cons = condis.empty() ? false : true;
                for(auto& iter : record)
                {
                    DATATYPE type = iter.second.first;
                    if(type == DATATYPE::DATA_INT)
                    {
                        wheres += iter.first + "=" + x_sql_builder::escapeString(mysql_ref,iter.second.second);
                    }
                    else if(type == DATATYPE::DATA_STRING)
                    {
                        wheres += iter.first + "=" + "\"" + iter.second.second + "\"";
                    }
                    if(!condis.empty())
                    {
                        std::string top = condis.front();
                        if(top == "and" || top=="or")
                            wheres += " " + top + " ";
                        condis.pop();
                    }
                }
                if(is_has_cons)
                    wheres.pop_back();
                std::string sql = str + field_names + " from " + table_name + wheres;
                return sql;
            }
    };
    class x_update_sql_builder{
        public:
            static std::string build(MYSQL* mysql_ref,const std::string& table_name,const DataRecord& record,\
            const DataRecord& wheres,Conditions& condis)
            {
                if(!mysql_ref) return "";
                //update stus set stu_name='孙七' where stu_num='20210105';
                std::string str = "update " + table_name +" set ";
                std::string field_names = "" , wheres_str = " where ";
                for(auto& iter : record)
                {
                    DATATYPE type = iter.second.first;
                    if(type == DATATYPE::DATA_INT)
                    {
                        field_names += iter.first + "=" + x_sql_builder::escapeString(mysql_ref,iter.second.second);
                    }
                    else if(type == DATATYPE::DATA_STRING)
                    {
                        field_names += iter.first + "=" + "\"" + iter.second.second +"\"";
                    }
                }
                bool is_has_cons = condis.empty() ? false : true;
                for(auto& iter : wheres)
                {
                    DATATYPE type = iter.second.first;
                    if(type == DATATYPE::DATA_INT)
                    {
                        wheres_str += iter.first + "=" + iter.second.second;
                    }
                    else if(type == DATATYPE::DATA_STRING)
                    {
                        wheres_str += iter.first + "=" + "\"" + x_sql_builder::escapeString(mysql_ref,iter.second.second) +"\"";
                    }
                    if(!condis.empty())
                    {
                        std::string top = condis.front();
                        if(top == "and" || top=="or")
                            wheres_str += " " + top + " ";
                        condis.pop();
                    }
                }
                if(is_has_cons)
                    wheres_str.pop_back();
                std::string sql = str + field_names + wheres_str;
                return sql;
            }
    };

    class x_delete_sql_builder{
        public:
            static std::string build(MYSQL* mysql_ref,const std::string& table_name,const DataRecord& record,Conditions& condis)
            {
                if(!mysql_ref) return "";
                //delete from stus where stu_num='20210102';
                std::string str = "delete from " + table_name + " ";
                std::string wheres = "where ";
                bool is_has_cons = condis.empty() ? false : true;
                for(auto& iter : record)
                {
                    DATATYPE type = iter.second.first;
                    if(type == DATATYPE::DATA_INT)
                    {
                        wheres += iter.first + "=" + iter.second.second;
                    }
                    else if(type == DATATYPE::DATA_STRING)
                    {
                        wheres += iter.first + "=" + "\"" + x_sql_builder::escapeString(mysql_ref,iter.second.second) +"\"";
                    }
                    if(!condis.empty())
                    {
                        std::string top = condis.front();
                        if(top == "and" || top=="or")
                            wheres += " " + top + " ";
                        condis.pop();
                    }
                }
                if(is_has_cons)
                    wheres.pop_back();
                std::string sql = str + wheres;
                return sql;
            }  
    };
}

#endif